package impl

import (
	"context"

	"gitee.com/keepalived_0807/Vblog/apps/token"
	"gitee.com/keepalived_0807/Vblog/apps/user"
	"gitee.com/keepalived_0807/Vblog/conf"
	"gitee.com/keepalived_0807/Vblog/exception"
	"gitee.com/keepalived_0807/Vblog/ioc"
	"gorm.io/gorm"
)

type TokenServiceImpl struct {
	db   *gorm.DB
	user user.Service
}

// func NewTokenServiceImpl(UserServiceImpl user.Service) *TokenServiceImpl {
// 	return &TokenServiceImpl{
// 		db:   conf.C().MySQL.GetDB(),
// 		user: UserServiceImpl,
// 	}
// }

func init() {
	ioc.Controller.Registry(token.AppName, &TokenServiceImpl{})
}

func (t *TokenServiceImpl) Init() error {
	t.db = conf.C().MySQL.GetDB()
	t.user = ioc.Controller.Get(user.AppName).(user.Service)
	return nil
}

func (t *TokenServiceImpl) IssueToken(ctx context.Context, in *token.IssueTokenRequest) (*token.Token, error) {
	// 1、查询用户对象
	user := user.NewQueryUserRequest()
	user.Username = in.Username
	us, err := t.user.QueryUser(ctx, user)
	if err != nil {
		return nil, err
	}
	if len(us.Items) == 0 {
		return nil, token.ErrAuthFailed
	}
	u := us.Items[0]
	if err := u.CheckPassword(in.Password); err != nil {
		return nil, token.ErrAuthFailed
	}

	tk := token.NewToken(u)
	if err := t.db.WithContext(ctx).Create(tk).Error; err != nil {
		return nil, exception.ErrServerInternalError("保存报错，%s", err)
	}
	return tk, nil
}

// 令牌校验
func (t *TokenServiceImpl) ValidateToken(ctx context.Context, in *token.ValidateTokenRequest) (*token.Token, error) {
	tk := token.DefaultToken()
	err := t.db.WithContext(ctx).Where("access_token = ?", in.AccessToken).First(tk).Error
	if err == gorm.ErrRecordNotFound {
		return nil, exception.ErrNotFound("Token未找到")
	}
	if err != nil {
		return nil, exception.ErrServerInternalError("查询报错，%s", err)
	}
	if err := tk.RefreshTokenIsExpired(); err != nil {
		return nil, err
	}
	if err := tk.AccessTokenIsExpired(); err != nil {
		return nil, err
	}
	return tk, nil
}

// 令牌撤销
func (t *TokenServiceImpl) RevolkToken(ctx context.Context, in *token.RevolkTokenRequest) (*token.Token, error) {
	tk := token.DefaultToken()
	err := t.db.WithContext(ctx).Where("access_token = ?", in.AccessToken).First(tk).Delete(token.Token{}).Error
	if err == gorm.ErrRecordNotFound {
		return nil, exception.ErrNotFound("Token未找到")
	}

	if tk.RefreshToken != in.RefreshToken {
		return nil, token.ErrRefreshTokenFailed
	}

	err = t.db.WithContext(ctx).Where("access_token = ?", in.AccessToken).Error
	if err != nil {
		return nil, err
	}
	return tk, err
}
